// controllers/role_controller.go
package controllers

import (
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"

	"go-admin-system/models"
)

type RoleController struct {
	db *gorm.DB
}

func NewRoleController(db *gorm.DB) *RoleController {
	return &RoleController{db}
}

// GetRoles 获取所有角色
func (rc *RoleController) GetRoles(c *gin.Context) {
	startTime := time.Now()

	log.Printf("获取角色列表 [开始] - IP: %s", c.ClientIP())

	var roles []models.Role
	if err := rc.db.Find(&roles).Error; err != nil {
		log.Printf("获取角色列表 [数据库查询失败] - IP: %s, 耗时: %v, 错误: %v",
			c.ClientIP(), time.Since(startTime), err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取角色列表失败"})
		return
	}

	log.Printf("获取角色列表 [成功] - 角色数量: %d, IP: %s, 耗时: %v",
		len(roles), c.ClientIP(), time.Since(startTime))

	c.JSON(http.StatusOK, gin.H{"roles": roles})
}

// GetRole 获取单个角色
func (rc *RoleController) GetRole(c *gin.Context) {
	startTime := time.Now()
	roleID := c.Param("id")

	log.Printf("获取角色 [开始] - 角色ID: %s, IP: %s", roleID, c.ClientIP())

	var role models.Role
	if err := rc.db.Preload("Permissions").Preload("Menus").First(&role, roleID).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			log.Printf("获取角色 [角色不存在] - 角色ID: %s, IP: %s, 耗时: %v",
				roleID, c.ClientIP(), time.Since(startTime))
			c.JSON(http.StatusNotFound, gin.H{"error": "角色不存在"})
		} else {
			log.Printf("获取角色 [数据库查询失败] - 角色ID: %s, IP: %s, 耗时: %v, 错误: %v",
				roleID, c.ClientIP(), time.Since(startTime), err)
			c.JSON(http.StatusInternalServerError, gin.H{"error": "获取角色失败"})
		}
		return
	}

	log.Printf("获取角色 [成功] - 角色ID: %d, 角色名: %s, IP: %s, 耗时: %v",
		role.ID, role.Name, c.ClientIP(), time.Since(startTime))

	c.JSON(http.StatusOK, gin.H{"role": role})
}

// CreateRole 创建角色
func (rc *RoleController) CreateRole(c *gin.Context) {
	startTime := time.Now()

	var input struct {
		Name        string `json:"name" binding:"required"`
		Description string `json:"description"`
		Status      int    `json:"status"`
	}

	if err := c.ShouldBindJSON(&input); err != nil {
		log.Printf("创建角色 [参数绑定失败] - IP: %s, 耗时: %v, 错误: %v",
			c.ClientIP(), time.Since(startTime), err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数格式错误"})
		return
	}

	log.Printf("创建角色 [开始处理] - 角色名: %s, IP: %s, 耗时: %v",
		input.Name, c.ClientIP(), time.Since(startTime))

	// 检查角色名是否已存在
	var existingRole models.Role
	if err := rc.db.Where("name = ?", input.Name).First(&existingRole).Error; err == nil {
		log.Printf("创建角色 [角色名已存在] - 角色名: %s, IP: %s, 耗时: %v",
			input.Name, c.ClientIP(), time.Since(startTime))
		c.JSON(http.StatusConflict, gin.H{"error": "角色名已存在"})
		return
	}

	role := models.Role{
		Name:        input.Name,
		Description: input.Description,
		Status:      input.Status,
	}

	if err := rc.db.Create(&role).Error; err != nil {
		log.Printf("创建角色 [数据库创建失败] - 角色名: %s, IP: %s, 耗时: %v, 错误: %v",
			input.Name, c.ClientIP(), time.Since(startTime), err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建角色失败"})
		return
	}

	log.Printf("创建角色 [成功] - 角色ID: %d, 角色名: %s, IP: %s, 耗时: %v",
		role.ID, role.Name, c.ClientIP(), time.Since(startTime))

	c.JSON(http.StatusCreated, gin.H{"role": role})
}

// UpdateRole 更新角色
func (rc *RoleController) UpdateRole(c *gin.Context) {
	startTime := time.Now()
	roleID := c.Param("id")

	log.Printf("更新角色 [开始] - 角色ID: %s, IP: %s", roleID, c.ClientIP())

	var role models.Role
	if err := rc.db.First(&role, roleID).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			log.Printf("更新角色 [角色不存在] - 角色ID: %s, IP: %s, 耗时: %v",
				roleID, c.ClientIP(), time.Since(startTime))
			c.JSON(http.StatusNotFound, gin.H{"error": "角色不存在"})
		} else {
			log.Printf("更新角色 [查询原角色失败] - 角色ID: %s, IP: %s, 耗时: %v, 错误: %v",
				roleID, c.ClientIP(), time.Since(startTime), err)
			c.JSON(http.StatusInternalServerError, gin.H{"error": "查询角色失败"})
		}
		return
	}

	var input struct {
		Name        string `json:"name"`
		Description string `json:"description"`
		Status      int    `json:"status"`
	}

	if err := c.ShouldBindJSON(&input); err != nil {
		log.Printf("更新角色 [参数绑定失败] - 角色ID: %d, 角色名: %s, IP: %s, 耗时: %v, 错误: %v",
			role.ID, role.Name, c.ClientIP(), time.Since(startTime), err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数格式错误"})
		return
	}

	log.Printf("更新角色 [处理参数] - 角色ID: %d, 原角色名: %s, 新角色名: %s, IP: %s, 耗时: %v",
		role.ID, role.Name, input.Name, c.ClientIP(), time.Since(startTime))

	// 检查新角色名是否已存在
	if input.Name != "" && input.Name != role.Name {
		var existingRole models.Role
		if err := rc.db.Where("name = ?", input.Name).First(&existingRole).Error; err == nil {
			log.Printf("更新角色 [新角色名已存在] - 角色ID: %d, 原角色名: %s, 新角色名: %s, IP: %s, 耗时: %v",
				role.ID, role.Name, input.Name, c.ClientIP(), time.Since(startTime))
			c.JSON(http.StatusConflict, gin.H{"error": "角色名已存在"})
			return
		}
	}

	// 记录原始值
	oldName := role.Name
	oldDescription := role.Description
	oldStatus := role.Status

	if input.Name != "" {
		role.Name = input.Name
	}

	if input.Description != "" {
		role.Description = input.Description
	}

	role.Status = input.Status

	if err := rc.db.Save(&role).Error; err != nil {
		log.Printf("更新角色 [数据库保存失败] - 角色ID: %d, 原角色名: %s, 新角色名: %s, IP: %s, 耗时: %v, 错误: %v",
			role.ID, oldName, role.Name, c.ClientIP(), time.Since(startTime), err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新角色失败"})
		return
	}

	log.Printf("更新角色 [成功] - 角色ID: %d, 原角色名: %s, 新角色名: %s, 原描述: %s, 新描述: %s, 原状态: %d, 新状态: %d, IP: %s, 耗时: %v",
		role.ID, oldName, role.Name, oldDescription, role.Description, oldStatus, role.Status, c.ClientIP(), time.Since(startTime))

	c.JSON(http.StatusOK, gin.H{"role": role})
}

// DeleteRole 删除角色
func (rc *RoleController) DeleteRole(c *gin.Context) {
	startTime := time.Now()
	roleID := c.Param("id")

	log.Printf("删除角色 [开始] - 角色ID: %s, IP: %s", roleID, c.ClientIP())

	var role models.Role
	if err := rc.db.First(&role, roleID).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			log.Printf("删除角色 [角色不存在] - 角色ID: %s, IP: %s, 耗时: %v",
				roleID, c.ClientIP(), time.Since(startTime))
			c.JSON(http.StatusNotFound, gin.H{"error": "角色不存在"})
		} else {
			log.Printf("删除角色 [查询角色失败] - 角色ID: %s, IP: %s, 耗时: %v, 错误: %v",
				roleID, c.ClientIP(), time.Since(startTime), err)
			c.JSON(http.StatusInternalServerError, gin.H{"error": "查询角色失败"})
		}
		return
	}

	log.Printf("删除角色 [开始删除关联数据] - 角色ID: %d, 角色名: %s, IP: %s",
		role.ID, role.Name, c.ClientIP())

	// 先删除关联表数据
	if err := rc.db.Where("role_id = ?", role.ID).Delete(&models.RolePermission{}).Error; err != nil {
		log.Printf("删除角色 [删除角色权限关联失败] - 角色ID: %d, 角色名: %s, IP: %s, 错误: %v",
			role.ID, role.Name, c.ClientIP(), err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除角色关联数据失败"})
		return
	}

	if err := rc.db.Where("role_id = ?", role.ID).Delete(&models.RoleMenu{}).Error; err != nil {
		log.Printf("删除角色 [删除角色菜单关联失败] - 角色ID: %d, 角色名: %s, IP: %s, 错误: %v",
			role.ID, role.Name, c.ClientIP(), err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除角色关联数据失败"})
		return
	}

	if err := rc.db.Delete(&role).Error; err != nil {
		log.Printf("删除角色 [数据库删除失败] - 角色ID: %d, 角色名: %s, IP: %s, 耗时: %v, 错误: %v",
			role.ID, role.Name, c.ClientIP(), time.Since(startTime), err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除角色失败"})
		return
	}

	log.Printf("删除角色 [成功] - 角色ID: %d, 角色名: %s, IP: %s, 耗时: %v",
		role.ID, role.Name, c.ClientIP(), time.Since(startTime))

	c.JSON(http.StatusOK, gin.H{"message": "角色删除成功"})
}

// AssignPermissions 分配权限给角色
func (rc *RoleController) AssignPermissions(c *gin.Context) {
	startTime := time.Now()
	roleID := c.Param("id")

	log.Printf("分配权限 [开始] - 角色ID: %s, IP: %s", roleID, c.ClientIP())

	var role models.Role
	if err := rc.db.First(&role, roleID).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			log.Printf("分配权限 [角色不存在] - 角色ID: %s, IP: %s, 耗时: %v",
				roleID, c.ClientIP(), time.Since(startTime))
			c.JSON(http.StatusNotFound, gin.H{"error": "角色不存在"})
		} else {
			log.Printf("分配权限 [查询角色失败] - 角色ID: %s, IP: %s, 耗时: %v, 错误: %v",
				roleID, c.ClientIP(), time.Since(startTime), err)
			c.JSON(http.StatusInternalServerError, gin.H{"error": "查询角色失败"})
		}
		return
	}

	var input struct {
		PermissionIDs []uint `json:"permission_ids" binding:"required"`
	}

	if err := c.ShouldBindJSON(&input); err != nil {
		log.Printf("分配权限 [参数绑定失败] - 角色ID: %d, 角色名: %s, IP: %s, 耗时: %v, 错误: %v",
			role.ID, role.Name, c.ClientIP(), time.Since(startTime), err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数格式错误"})
		return
	}

	log.Printf("分配权限 [处理权限分配] - 角色ID: %d, 角色名: %s, 权限数量: %d, IP: %s, 耗时: %v",
		role.ID, role.Name, len(input.PermissionIDs), c.ClientIP(), time.Since(startTime))

	// 先删除角色现有的权限关联
	if err := rc.db.Where("role_id = ?", role.ID).Delete(&models.RolePermission{}).Error; err != nil {
		log.Printf("分配权限 [删除原有关联失败] - 角色ID: %d, 角色名: %s, IP: %s, 耗时: %v, 错误: %v",
			role.ID, role.Name, c.ClientIP(), time.Since(startTime), err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "分配权限失败"})
		return
	}

	// 添加新的权限关联
	for i, permissionID := range input.PermissionIDs {
		rolePermission := models.RolePermission{
			RoleID:       role.ID,
			PermissionID: permissionID,
		}

		if err := rc.db.Create(&rolePermission).Error; err != nil {
			log.Printf("分配权限 [创建权限关联失败] - 角色ID: %d, 角色名: %s, 权限ID: %d, 序号: %d, IP: %s, 错误: %v",
				role.ID, role.Name, permissionID, i, c.ClientIP(), err)
			c.JSON(http.StatusInternalServerError, gin.H{"error": "分配权限失败"})
			return
		}
	}

	log.Printf("分配权限 [重新加载角色权限] - 角色ID: %d, 角色名: %s, IP: %s",
		role.ID, role.Name, c.ClientIP())

	// 重新加载角色的权限
	if err := rc.db.Preload("Permissions").First(&role, role.ID).Error; err != nil {
		log.Printf("分配权限 [重新加载权限失败] - 角色ID: %d, 角色名: %s, IP: %s, 错误: %v",
			role.ID, role.Name, c.ClientIP(), err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取角色权限失败"})
		return
	}

	log.Printf("分配权限 [成功] - 角色ID: %d, 角色名: %s, 权限数量: %d, IP: %s, 总耗时: %v",
		role.ID, role.Name, len(role.Permissions), c.ClientIP(), time.Since(startTime))

	c.JSON(http.StatusOK, gin.H{"role": role})
}
